package com.time.tell.the.truth.netty.client;

import com.time.tell.the.truth.netty.dto.User;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.atomic.AtomicReference;

@Slf4j
public class Client {

  private final AtomicReference<Channel> channelHolder = new AtomicReference<>();

  public void send(User user) {
    log.info("send user: {}", user);
    channelHolder.get().writeAndFlush(user);
  }

  public void close() throws InterruptedException {
    channelHolder.get().close().sync();
  }

  public void connect() throws InterruptedException {
    EventLoopGroup workerGroup = new NioEventLoopGroup(1);
    Bootstrap b = new Bootstrap();
    b.group(workerGroup);
    b.channel(NioSocketChannel.class);
    b.option(ChannelOption.SO_KEEPALIVE, true);
    b.option(ChannelOption.TCP_NODELAY, true);
    b.handler(new ChannelInitializer<SocketChannel>() {
      @Override
      public void initChannel(SocketChannel ch) {
        ch.pipeline().addLast(new ClientWriteHandler());
        ch.pipeline().addLast(new ClientReadHandler());
      }
    });

    ChannelFuture f = b.connect("localhost", 8765).sync();

    channelHolder.set(f.channel());
    log.info("connect to server success");

    // 连接被关闭时，清理epoll对应的资源
    f.channel()
            .closeFuture()
            .addListener(cf -> workerGroup.shutdownGracefully());
  }

  public static void main(String[] args) throws InterruptedException {
    Client client = new Client();
    client.connect();
    client.send(new User("tttt", 3));

    // 休眠2秒，等待服务端响应
    Thread.sleep(2000);
    client.close();
    log.info("exit......");
  }
}
